﻿using System;
using System.Windows;
using System.Windows.Threading;

namespace SharpDepend.WPF
{
    internal class GUITimerManager : IGUITimerManager
    {
        internal class GuiTimer : IGuiTimer
        {
            private TimeSpan mInterval;
            private bool mRunning;
            private bool mQueryStoped;

            private bool mUsesInWindowsForms;
            private DispatcherTimer mNativeTimer;

            public GuiTimer(bool usesInWindowsForms)
            {
                mUsesInWindowsForms = usesInWindowsForms;

                if (usesInWindowsForms)
                {
                    mNativeTimer = new DispatcherTimer(DispatcherPriority.Normal);
                }
            }

            public TimeSpan Interval
            {
                get
                {
                    return mInterval;
                }
                set
                {
                    mInterval = value;

                    if (mUsesInWindowsForms)
                    {
                        mNativeTimer.Interval = value;
                    }
                }
            }

            public event Action Tick;

            public void Start()
            {
                if (mUsesInWindowsForms)
                {
                    mNativeTimer.Interval = mInterval;
                    mNativeTimer.Tick += Loop_WindowsForms;
                    mNativeTimer.Start();
                }
                else
                {
                    SharpDepend.Manager.ThreadManager.RunThread("Gui timer thread", (Action)Loop);
                }
            }

            public void Stop()
            {
                if (mUsesInWindowsForms)
                {
                    mNativeTimer.Stop();
                }
                else
                {
                    mRunning = false;
                }

                // Commend: Deadlock if we are waiting for it with the new GUI timer.
                //while (!mQueryStoped)
                //{
                //    SharpDepend.Manager.ThreadManager.Sleep(10);
                //}
            }

            private void Loop()
            {
                mQueryStoped = false;
                mRunning = true;

                // Wait until initialized.
                WaitUntilInitializedDone();

                while (mRunning)
                {
                    if (Tick != null)
                    {
                        var current = Application.Current;

                        if (current == null)
                        {
                            // Application has exit. Close of this thread.
                            return;
                        }

                        current.Dispatcher.Invoke(
                            (Action)delegate
                            {
                                if (mRunning)
                                {
                                    Tick();
                                }
                            }, null);
                    }

                    if (mInterval.TotalMilliseconds > 0)
                    {
                        SharpDepend.Manager.ThreadManager.Sleep((int)mInterval.TotalMilliseconds);
                    }
                }
                mQueryStoped = true;
            }

            private void Loop_WindowsForms(object sender, EventArgs args)
            {
                if (Tick != null)
                {
                    Tick();
                }
            }

            [System.Diagnostics.DebuggerStepThrough()]
            private void WaitUntilInitializedDone()
            {
                while (true)
                {
                    SharpDepend.Manager.ThreadManager.Sleep(10);
                
                    try
                    {
                        var mainView = Application.Current;
                
                        if (mainView == null)
                        {
                            continue;
                        }
                        else
                        {
                            if (mainView.Dispatcher == null)
                            {
                                continue;
                            }
                        }
                    }
                    catch (Exception)
                    {
                        continue;
                    }
                
                    break;
                }
            }
        }

        private bool mUsesInWindowsForms;

        public GUITimerManager(bool usesInWindowsForms)
        {
            mUsesInWindowsForms = usesInWindowsForms;
        }

        public IGuiTimer CreateTimer()
        {
            return new GuiTimer(mUsesInWindowsForms);
        }
    }
}
//using System;
//using System.Windows.Threading;

//namespace SharpDepend.WPF
//{
//    internal class GUITimerManager : IGUITimerManager
//    {
//        internal class GuiTimer : IGuiTimer
//        {
//            private DispatcherTimer mNativeTimer;
//            private TimeSpan mInterval;

//            public GuiTimer()
//            {
//                mNativeTimer = new DispatcherTimer(DispatcherPriority.Render);
//            }

//            public TimeSpan Interval
//            {
//                get
//                {
//                    return mInterval;
//                }
//                set
//                {
//                    mInterval = value;
//                    mNativeTimer.Interval = value;
//                }
//            }

//            public event Action Tick;

//            public void Start()
//            {
//                mNativeTimer.Interval = mInterval;
//                mNativeTimer.Tick += Loop;
//                mNativeTimer.Start();
//            }

//            public void Stop()
//            {
//                mNativeTimer.Stop();
//            }

//            private void Loop(object sender, EventArgs e)
//            {
//                if (Tick != null)
//                {
//                    Tick();
//                }
//            }
//        }

//        public IGuiTimer CreateTimer()
//        {
//            return new GuiTimer();
//        }
//    }
//}
